package com.lsa.letcode.the150.evalRpn;

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.util.List;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.junit.Before;
import org.junit.Test;

public class EvalRpnTest {
	private ScriptEngineManager m;
	private ScriptEngine e;

	@Before
	public void setup() {
		m = new ScriptEngineManager();
        e = m.getEngineByExtension("js");
	}
	
	@Test
	public void test() throws Exception {
		test("6 - 8 - 7", null, -9);
		test("(6)-(8)-(7)+(1+(6))", null, -2);
		
		test("1 - 2 + 3", null, 2);
		
		test("( (2+3) *4+  (5-6) *7)-8", Arrays.asList("2", "3", "+", "4", "*",
				"5", "6", "-", "7", "*", "+", "8", "-"), 5);
		
		test("1 - 24 / 4 + 6", null, 1);
		test("30 - 24 / 4 * 5 + 6", null, 6);
		
		test("2 + 3 * 4 - 5", null, 9);
		test("2 + 3", null, 5);
		test("1+1", null, 2);
		
		test("2", null, 2);
		test("(2+3) *4", null, 20);
		test("4 * (2+3)", null, 20);
		test("4 * (2+3) - 4 * (2+3)", null, 0);
		test("20 /5 + 20 / 5", null, 8);
		test("( ( (1+2)*9 - (3-4) ) + ( (5+6) - (7-8)*11 ) / 22 )", null, 29);
		test("(1+ (4+5+2)-3)+ (6+8)", null, 23);
		
		
		Solution s = new Solution();
		assertEquals(23, s.calculate("(1+ (4+5+2)-3)+ (6+8)"));
		
//		
//		Solution s = new Solution();
//		assertEquals(Arrays.asList("(", "(", "22", "+", "1", ")", "*", "33",
//				"+", "(", "4", "-", "6", ")", "*", "7", ")", "-", "6"),
//				Arrays.asList(s.tokenize("( (22+1) *33+  (4-6) *7)-6")));
//		assertEquals(Arrays.asList("2", "3", "4", "*", "4", "-", "+"),
//				Arrays.asList(s.toRPN("2 + 3 * 4 - 4")));
//		
//		System.out.println(Arrays.toString(s.toRPN("2 + 3 * 4 - 5")));
//		System.out.println(s.evalRPN(s.toRPN("2 + 3 * 4 - 5")));
		//2 + 24 / 4 - 4
	}
	
	private void test(String expr, List<String> expectedRpn, int expectedVal) {
		Solution s = new Solution();
		String[] rpn = s.toRPN(expr);
//		System.out.println(Arrays.toString(rpn));
		if (expectedRpn != null){
			assertEquals(expectedRpn, Arrays.asList(rpn));
		}
		assertEquals(expectedVal, s.evalRPN(rpn));
	}
	
	private int evalByJs(String expr) throws ScriptException {
        Double r = (Double)e.eval(expr);
		return r.intValue();
	}
}
